package com.supporter.sysbench;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xunaidong
 * @date 2021/8/8
 */
public class ThreadPoolContext{
    private final static Logger log = LoggerFactory.getLogger(ThreadPoolContext.class);
    private final GlobalProperties globalProperties;
    private final ThreadPoolExecutor executor;

    public ThreadPoolContext(GlobalProperties globalProperties) {
        this.globalProperties = globalProperties;
        executor  = new ThreadPoolExecutor(globalProperties.getThreads(),globalProperties.getThreads(),
                globalProperties.getDuration()+1, TimeUnit.SECONDS, new LinkedBlockingQueue(),
                new NamedThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        executor.prestartAllCoreThreads();
        log.info("初始化线程池完成,线程数量:{}.",globalProperties.getThreads());
    }

    public void destroy(){
        if(executor!=null&&!executor.isShutdown()){
            executor.shutdown();
            log.info("线程池关闭.");
        }
    }

    public void execute(Runnable work){
        Assert.notNull(work,"Runnable is null.");
        executor.execute(work);
    }

    private static class NamedThreadFactory implements ThreadFactory {
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        NamedThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = "sysbench-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(this.group, r, this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }

            if (t.getPriority() != 5) {
                t.setPriority(5);
            }

            return t;
        }
    }

}
